/*
 * Created on May 22, 2007
 *
 * To change the template for this generated file go to
 * Window&gt;Preferences&gt;Java&gt;Code Generation&gt;Code and Comments
 */
package it.unibo.deis.lia.filters;

import Jama.*;
import java.awt.*;
import java.util.Vector;

public class LeastSquares implements IFilter{
	
	public IFilter genFilter(){
		return new LeastSquares();
	}
	
	/*public static void main(String[]argv){
		LeastSquares ls=new LeastSquares();
		Point point[]={
				new Point(0,50),
				new Point(1,51),
				new Point(2,49),
				new Point(3,51),
				new Point(4,54),
				new Point(5,50),
				new Point(6,48)
			};
		ls.computeLS(point);
		Vector<Double> valueSet=new Vector<Double>();
		valueSet.addElement(new Double(50));
		valueSet.addElement(new Double(51));
		valueSet.addElement(new Double(49));
		valueSet.addElement(new Double(51));
		valueSet.addElement(new Double(54));
		valueSet.addElement(new Double(50));
		valueSet.addElement(new Double(48));
		Double next=ls.nextValue(valueSet, 0);
		System.out.println("next "+next);
	}*/
	public Double nextValue(Vector<Double> valueSet){//, double costante){
		int degreePoly =  3; // note: 3 => second polynome
		int numPoints = valueSet.size();
		Double res=null;
		Matrix mat = new Matrix(numPoints,degreePoly);
		double ab[];
		Matrix bmat;
		
		for (int j=0;j<degreePoly;j++)
			for (int i=0;i<numPoints;i++)
				//mat.set(i,j,Math.pow(point[i].x/*/30.0*/,j));
				mat.set(i,j,Math.pow(i/*/30.0*/,j));

		// Set B Matrix
		bmat = new Matrix(numPoints,1);
		for (int i=0;i<numPoints;i++)
			//bmat.set(i,0,(/*300-*/point[i].y)/*/30.0*/);
			bmat.set(i,0,(valueSet.elementAt(i)));

		try {
			ab = mat.solve(bmat).getRowPackedCopy();
			/*for (int i=0;i<ab.length;i++){
				System.out.println("F: "+ab[i]);
			}*/
			//g.setColor(Color.red);
			//gf.init(ab);
			//plotFit(ab,point.length/*,g*/);
			//plotFit(ab,numPoints);
			res=new Double(getY(numPoints-1,ab));
		}
		catch(RuntimeException e){
			//e.printStackTrace();
			//System.out.println("Singular");
			//g.setColor(Color.red);
			//g.drawString("Matrix is singular",100,100);
			//double at[] = {0.0,0.0,0.0};
			//gf.init(at);
		}
		return res;
	}
	

	public void computeLS(Point point[]){
		//int max=75;
		int current=point.length;
		int numPoints = point.length;
		int degreePoly =  3; // note: 3 => second polynomial degree

		/*try {
			degreePoly = 1+(int)Integer.parseInt(c.getSelectedItem());
		} catch(NumberFormatException e){
			c.select(1);
			degreePoly = 2;
		}*/
		Matrix mat = new Matrix(numPoints,degreePoly);
		double ab[];
		Matrix bmat;
		
		/*if (cb.getState()){*/
			for (int j=0;j<degreePoly;j++)
				for (int i=0;i<current;i++)
					mat.set(i,j,Math.pow(point[i].x/*/30.0*/,j));

			// Set B Matrix
			bmat = new Matrix(current,1);
			for (int i=0;i<current;i++)
				bmat.set(i,0,(/*300-*/point[i].y)/*/30.0*/);

			try {
				ab = mat.solve(bmat).getRowPackedCopy();
				for (int i=0;i<ab.length;i++)
					System.out.println("F: "+ab[i]);
				//g.setColor(Color.red);
				//gf.init(ab);
				plotFit(ab,point.length/*,g*/);
			} catch(RuntimeException e){
				System.out.println("Singular");
				//g.setColor(Color.red);
				//g.drawString("Matrix is singular",100,100);
				//double at[] = {0.0,0.0,0.0};
				//gf.init(at);
			}
		/*} else {*
			for (int j=0;j<degreePoly;j++)
				for (int i=0;i<current;i++)
					mat.set(i,j,Math.pow((300-point[i].y)/30.0,j));

			// Set B Matrix
			bmat = new Jama.Matrix(current,1);
			for (int i=0;i<current;i++)
				bmat.set(i,0,(point[i].x)/30.0);
			
			try {
				ab = mat.solve(bmat).getRowPackedCopy();
				for (int i=0;i<current;i++)
					System.out.println("F: "+ab[i]);

				//g.setColor(Color.red);
				//plotFit2(ab,g);
				//gf.init(ab);
			} 
			catch(RuntimeException e){
				e.printStackTrace();
				System.out.println("Singular");
				//g.setColor(Color.red);
				//g.drawString("Matrix is singular",100,100);
			}/**/
		//}
	}

	public void plotFit2(double a[]/*, Graphics g*/){
		int intervalNum = 30;//size.width;
		double intervalSize = 10/(intervalNum*1.0);
		for (int i=0;i<intervalNum;i++)
			//drawThingy(getY(i*intervalSize,a),(i*intervalSize),getY((i+1)*intervalSize,a),((i+1)*intervalSize),g);
			System.out.println(getY(i*intervalSize,a)
					+" "+(i*intervalSize)
					+" "+getY((i+1)*intervalSize,a)
					+" "+((i+1)*intervalSize));

	}

	public void plotFit(double a[],int length/*, Graphics g*/){
		int intervalNum = length;//20;//size.width;
		double intervalSize = 1;//10/(intervalNum*1.0);
		for (int i=0;i<intervalNum;i++)
			//drawThingy(i*intervalSize,getY(i*intervalSize,a),(i+1)*intervalSize,getY((i+1)*intervalSize,a),g);
			System.out.println(getY(i*intervalSize,a)
				+" "+(i*intervalSize)
				+" "+getY((i+1)*intervalSize,a)
				+" "+((i+1)*intervalSize));

	}
	/*public void drawThingy(double x1, double y1, double x2, double y2,Graphics g){
		int ix1 = (int)Math.round(30*x1);
		int iy1 = 300-(int)Math.round(30*y1);
		int ix2 = (int)Math.round(30*x2);
		int iy2 = 300-(int)Math.round(30*y2);

		g.drawLine(ix1,iy1,ix2,iy2);
	}*/

	public double getY(double x, double a[]){
		double y = 0;
		for (int i=0;i<a.length;i++)
			y+= a[i]*Math.pow(x,i);

		return y;
	}

	/*public void drawPoints(Graphics g){
		g.setColor(Color.blue);
		for (int i=0;i<current;i++)
			g.fillOval(point[i].x,point[i].y,3,3);
	}

	public void drawTicks(Graphics g){
		g.setColor(new Color(220,220,200));
		for (int i=0;i*30<size.width;i++)
			g.drawLine(i*30,size.height,i*30,0);

		for (int i=0;i*30<size.height;i++)
			g.drawLine(0,i*30,size.width,i*30);

	}

	public boolean mouseDown(Event evt, int x, int y){
		addPoint(x,y);
		repaint();
		return true;
	}

	public void addExample(){
		addPointTen(0.0,2.9);
		addPointTen(0.5,2.7);
		addPointTen(1.0,4.8);
		addPointTen(1.5,5.3);
		addPointTen(2.0,7.1);
		addPointTen(2.5,7.6);
		addPointTen(3.0,7.7);
		addPointTen(3.5,7.6);
		addPointTen(4.0,9.4);
		addPointTen(4.5,9.0);
		addPointTen(5.0,9.6);
		addPointTen(5.5,10.0);
		addPointTen(6.0,10.2);
		addPointTen(6.5,9.7);
		addPointTen(7.0,8.3);
		addPointTen(7.5,8.4);
		addPointTen(8.0,9.0);
		addPointTen(8.5,8.3);
		addPointTen(9.0,6.6);
		addPointTen(9.5,6.7);
		addPointTen(10.0,4.1);
		repaint();
	}

	public void addPointTen(double x, double y){
		fitDraw = false;
		addPoint((int)Math.round(x*30),size.height-(int)Math.round(y*30));
	}

	public void addPoint(int x, int y){
		if (current < max-1) {
			point[current].x = x;
			point[current].y = y;
			if (current > 0)
				c.addItem(""+(current));
			current++;
		}
	}

	public void reset(){
		point = new Point[max];
		for (int i=0;i<max;i++)
			point[i] = new Point(-5,-5);
		current = 0;
		fitDraw = false;
		c.removeAll();
		c.addItem("???");	
		repaint();
	}*/


}
